<?php

namespace Xin\Setting\Laravel;

use Illuminate\Contracts\Config\Repository;
use Illuminate\Foundation\Application as LaravelApplication;
use Illuminate\Support\ServiceProvider;
use Laravel\Lumen\Application as LumenApplication;
use Xin\Setting\Contracts\Factory as SettingFactory;
use Xin\Setting\Contracts\Serializer as SettingSerializer;
use Xin\Setting\Laravel\Commands\ClearCommand;
use Xin\Setting\Laravel\Commands\ShowCommand;
use Xin\Setting\Laravel\Commands\UpdateCommand;
use Xin\Setting\Serializer;
use Xin\Setting\SettingManager;

class SettingServiceProvider extends ServiceProvider
{
	/**
	 * 注册任何应用程序服务。
	 *
	 * @return void
	 */
	public function register()
	{
		$this->registerManager();

		$this->registerCommands();
	}

	/**
	 * 注册站点配置管理器
	 * @return void
	 */
	protected function registerManager()
	{
		$this->app->singleton(SettingManager::class, function () {
			$manager = new SettingManager(
				$this->app['config']->get('setting') ?: [],
				$this->app['cache']->store(),
			);

			// 加载站点配置到系统配置中
			$this->setToSystemConfigResolver($manager);

			// 注册驱动器
			$this->registerDrivers($manager);

			return $manager;
		});
		$this->app->alias(SettingManager::class, 'setting');
		$this->app->alias(SettingManager::class, SettingFactory::class);

		$this->app->singleton('setting.repository', function ($app) {
			return $app['setting']->repository();
		});
		$this->app->singleton(SettingSerializer::class, Serializer::class);
		$this->app->alias(SettingSerializer::class, 'setting.serializer');
	}

	/**
	 * 注册驱动器
	 * @return void
	 */
	protected function registerDrivers(SettingManager $manager)
	{
		$handler = function ($name, $config){
			return new ModelRepository(
				$config,
				$this->app['setting.serializer']
			);
		};
		$manager->extend('model', $handler);
		$manager->extend('database', $handler);
	}

	/**
	 * 注册设置系统配置完成器
	 * @return void
	 */
	protected function setToSystemConfigResolver(SettingManager $manager)
	{
		$manager->setToSystemConfigResolver(function ($settings) {
			/** @var Repository $config */
			$config = $this->app['config'];
			$config->set($settings);
		});
	}

	/**
	 * 注册命令行脚本
	 * @return void
	 */
	protected function registerCommands()
	{
		$this->commands([
			ShowCommand::class,
			ClearCommand::class,
			UpdateCommand::class,
		]);
	}

	/**
	 * Register the config for publishing
	 *
	 */
	public function boot()
	{
		if ($this->app instanceof LaravelApplication && $this->app->runningInConsole()) {
			$this->publishes([$this->configPath() => config_path('setting.php')], 'setting');
		} elseif ($this->app instanceof LumenApplication) {
			$this->app->configure('setting');
		}

		$this->mergeConfigFrom($this->configPath(), 'setting');

		// 加载站点配置到系统配置中
		// 仅在非生产环境刷新缓存
		$refreshCache = $this->isRefreshCache();
		$this->app['setting']->loadToSystemConfig($refreshCache);
	}

	/**
	 * 是否刷新缓存
	 * @return bool
	 */
	protected function isRefreshCache()
	{
		if (($isDebug = config('app.debug')) !== null) {
			return (bool)$isDebug;
		}

		return !$this->app->environment(['production', 'staging']);
	}

	/**
	 * Set the config path
	 *
	 * @return string
	 */
	protected function configPath()
	{
		return __DIR__ . '/../../config.php';
	}
}
